<script lang="ts" setup>
import { ref, watch } from 'vue';

import { ElButton, ElProgress, ElUpload } from 'element-plus';

import { fileUploadR2PartUpload } from '#/api';

const emits = defineEmits(['change']);
const modelValue = defineModel<(Blob | object | string)[]>('modelValue', {
  default: [],
});
const videoList = ref<any[]>([]);
const isProcessing = ref(false);
// 视频配置
const videoConfig = ref({
  maxSize: 100 * 1024 * 1024, // 最大文件大小（100MB）
  maxDuration: 300, // 最大时长（秒）
  acceptedFormats: ['video/mp4', 'video/webm'], // 支持的格式
});

const percentage = ref(0);
const myProgress = ref(null);
// 处理视频上传
const onChange = async (uploadFile) => {
  const rawFile = uploadFile.raw;
  percentage.value = 0;
  // 更新model值
  modelValue.value = [
    {
      videoUrl: uploadFile,
      videoOssObjectKey: '',
      uploadId: '',
    },
  ];
};

// 分片上传
const sliceUpload = async () => {
  if (!!myProgress.value && myProgress.value.uploadId) {
    return reSliceUpload();
  }
  const { progress, promises } = await fileUploadR2PartUpload(
    modelValue.value[0].videoUrl,
  );
  myProgress.value = progress;
  await promises;
  percentage.value = Math.round(
    (myProgress.value.uploaded / myProgress.value.total) * 100,
  );
  return progress.uploaded == progress.total
    ? Promise.resolve({
        videoOssObjectKey: progress.ossObjectKey,
        uploadId: progress.uploadId,
        etagList: progress.uploadedChunks
          .sort((a, b) => {
            return a.partNum - b.partNum;
          })
          .map((item) => {
            return item.etag;
          }),
      })
    : Promise.reject({
        videoOssObjectKey: progress.ossObjectKey,
        uploadId: progress.uploadId,
        etagList: progress.uploadedChunks
          .sort((a, b) => {
            return a.partNum - b.partNum;
          })
          .map((item) => {
            return item.etag;
          }),
      });
};

const reSliceUpload = async () => {
  const { progress, promises } = await fileUploadR2PartUpload(
    modelValue.value[0].videoUrl,
    myProgress.value,
    true,
  );
  myProgress.value = progress;
  await promises;
  percentage.value = Math.round(
    (myProgress.value.uploaded / myProgress.value.total) * 100,
  );
  return progress.uploaded == progress.total
    ? Promise.resolve({
        videoOssObjectKey: progress.ossObjectKey,
        uploadId: progress.uploadId,
        etagList: progress.uploadedChunks
          .sort((a, b) => {
            return a.partNum - b.partNum;
          })
          .map((item) => {
            return item.etag;
          }),
      })
    : Promise.reject({
        videoOssObjectKey: progress.ossObjectKey,
        uploadId: progress.uploadId,
        etagList: progress.uploadedChunks
          .sort((a, b) => {
            return a.partNum - b.partNum;
          })
          .map((item) => {
            return item.etag;
          }),
      });
};

// 移除视频
const removeVideo = (index: number) => {
  videoList.value.splice(index, 1);
  modelValue.value.splice(index, 1);
  myProgress.value = null;
};

// 监听modelValue变化
watch(
  modelValue,
  (newValue) => {
    console.log('newValue', newValue);
    if (newValue.length === 0) {
      videoList.value = [];
    } else {
      videoList.value = newValue.map((item) => {
        // 区分字符串和Blob(File)类型
        return typeof item.videoUrl === 'string'
          ? {
              preview: item.videoUrl,
              name: item.videoUrl.split('/').pop(),
              rawFile: item.videoUrl,
            }
          : {
              preview: URL.createObjectURL(item.videoUrl.raw),
              name: item.videoUrl.name,
              rawFile: item.videoUrl,
            };
      });
    }
  },
  { deep: true },
);
defineExpose({
  sliceUpload,
});
</script>
<template>
  <div class="video-upload">
    <ElUpload
      :auto-upload="false"
      :disabled="isProcessing"
      :on-change="onChange"
      :show-file-list="false"
      accept="video/mp4,video/webm"
      action="#"
      class="upload-demo"
      drag
      multiple
    >
      <div class="flex w-full justify-center">
        <div class="el-upload__tip">
          支持MP4/WebM格式，大小不超过100MB，时长不超过5分钟
        </div>
      </div>
    </ElUpload>

    <!-- 视频预览列表 -->
    <div v-if="videoList.length > 0" class="preview-list">
      <div
        v-for="(video, index) in videoList"
        :key="index"
        class="preview-item"
      >
        <!-- 视频缩略图 -->
        <video
          :alt="video.name"
          :src="video.preview"
          class="preview-image"
          controls
        ></video>
        <!-- 进度条 -->
        <ElProgress
          v-if="!!myProgress && myProgress.total != myProgress.uploaded"
          :percentage="percentage"
          :stroke-width="16"
          :text-inside="true"
          class="upload-progress"
          status="success"
        />
        <ElButton
          v-if="!!myProgress && myProgress.total != myProgress.uploaded"
          type="primary"
          @click="reSliceUpload"
        >
          继续上传
        </ElButton>
        <div class="preview-info">
          <span class="preview-name">{{ video.name }}</span>
        </div>

        <div class="preview-remove" @click.stop="removeVideo(index)">
          <i class="el-icon-delete">×</i>
        </div>
      </div>
    </div>
  </div>
</template>
<style scoped>
.video-upload {
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
}

.upload-area {
  width: 100%;
  padding: 40px;
  text-align: center;
  cursor: pointer;
  border: 2px dashed #ddd;
  border-radius: 6px;
  transition: border-color 0.3s;
}

.upload-area:hover:not([disabled]) {
  border-color: #409eff;
}

.el-upload__tip {
  margin-top: 10px;
  font-size: 12px;
  color: #909399;
}

.preview-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 20px;
  margin-top: 20px;
}

.preview-item {
  position: relative;
  overflow: hidden;
  border-radius: 6px;
  box-shadow: 0 2px 12px rgb(0 0 0 / 10%);
}

.preview-image {
  width: 100%;
  height: 150px;
  object-fit: cover;
}

.preview-info {
  padding: 12px;
  background: #f5f7fa;
}

.preview-name {
  display: block;
  overflow: hidden;
  font-size: 14px;
  color: #606266;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.preview-remove {
  position: absolute;
  top: 5px;
  right: 5px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  color: white;
  cursor: pointer;
  background: rgb(0 0 0 / 50%);
  border-radius: 50%;
  opacity: 0;
  transition: opacity 0.3s;
}

.preview-item:hover .preview-remove {
  opacity: 1;
}

.play-button {
  position: absolute;
  top: 50%;
  left: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 50px;
  height: 50px;
  cursor: pointer;
  background: rgb(0 0 0 / 50%);
  border-radius: 50%;
  transition: background-color 0.3s;
  transform: translate(-50%, -50%);
}

.play-button:hover {
  background: rgb(0 0 0 / 70%);
}

.play-icon {
  font-size: 24px;
  color: white;
}

.upload-progress {
  /* position: absolute;
  right: 0;
  bottom: 0;
  left: 0; */
}

/* 处理状态样式 */
.upload-area[disabled] {
  cursor: not-allowed;
  opacity: 0.7;
}
</style>
